package com.sirdc.modules.paas.api.common.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import com.sirdc.modules.paas.api.common.Constants;

/**
 * htpp请求工具类.
 * 支持SSL请求.
 * 
 * @author Qing
 * @e-mail lhq@suncco.com
 * @version v1.0
 * @copyright 2010-2015
 * @create-time 2013-9-18 下午6:08:52
 * 
 */
public class HttpClientUtil {

	/**
	 * 获取GET请求返回的字符串信息.
	 * @param requsetUrl 请求地址.
	 * @param parameters 请求参数.
	 * @return
	 */
	public static String httpPost(String requsetUrl, Map<String, Object> parameters) {
		URL url = null;
		HttpURLConnection connection = null;
		try {
			url = new URL(requsetUrl);
			connection = (HttpURLConnection) url.openConnection();
		} catch (IOException e) {
			System.out.println("创建http连接出错:" + e.getMessage());
			e.printStackTrace();
		}
		// 判断是否是https连接.
		if (connection instanceof HttpsURLConnection) {
			((HttpsURLConnection) connection).setSSLSocketFactory(getSimpleSSLSocketFactory());
		}
		// 设置公共的请求参数.
		connection.setDoOutput(true);
		connection.setConnectTimeout(Constants.CONNECT_TIMEOUT);
		connection.setReadTimeout(Constants.READ_TIMEOUT);
		// 设置POST请求参数.
		try {
			connection.setRequestMethod("POST");
			// POST请求不能使用缓存
	        connection.setUseCaches(false);
	        // URLConnection.setInstanceFollowRedirects是成员函数，仅作用于当前函数
	        connection.setInstanceFollowRedirects(true);
	        // 配置本次连接的Content-type，配置为application/x-www-form-urlencoded的
	        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
//	        connection.setRequestProperty("Content-type", "application/x-java-serialized-object");
		} catch (ProtocolException e) {
			System.out.println("设置POST请求参数出错:" + e.getMessage());
			e.printStackTrace();
		}
		// 设置请求参数.
		byte[] b = setHttpParams(parameters, Constants.CHARSET).toString().getBytes();
		if (b != null && b.length > 0) {
			try {
//				DataOutputStream out = new DataOutputStream(connection.getOutputStream());
//				out.write(b, 0, b.length);
				connection.getOutputStream().write(b, 0, b.length);
				connection.getOutputStream().flush();
				connection.getOutputStream().close();
			} catch (IOException e) {
				System.out.println("设置POST请求参数出错:" + e.getMessage());
				e.printStackTrace();
			}
		}
		// 获取请求返回的结果.
		return readResponseContent(connection, Constants.CHARSET);
	}

	/**
	 * 获取GET请求返回的字符串信息.
	 * @param requsetUrl 请求地址.
	 * @param parameters 请求参数.
	 * @return
	 */
	public static String httpGet(String requsetUrl, Map<String, Object> parameters) {
		URL url = null;
		HttpURLConnection connection = null;
		try {
			url = new URL(requsetUrl);
			connection = (HttpURLConnection) url.openConnection();
		} catch (IOException e) {
			System.out.println("创建http连接出错:" + e.getMessage());
			e.printStackTrace();
		}
		// 判断是否是https连接.
		if (connection instanceof HttpsURLConnection) {
			((HttpsURLConnection) connection).setSSLSocketFactory(getSimpleSSLSocketFactory());
		}
		// 设置公共的请求参数.
		connection.setConnectTimeout(Constants.CONNECT_TIMEOUT);
		connection.setReadTimeout(Constants.READ_TIMEOUT);
		// 设置GET请求.
		try {
			connection.setRequestMethod("GET");
		} catch (ProtocolException e) {
			System.out.println("设置GET请求出错:" + e.getMessage());
			e.printStackTrace();
		}
		// 设置请求参数.
		byte[] b = setHttpParams(parameters, Constants.CHARSET).toString().getBytes();
		if (b != null && b.length > 0) {
			try {
				connection.getOutputStream().write(b, 0, b.length);
				connection.getOutputStream().flush();
				connection.getOutputStream().close();
			} catch (IOException e) {
				System.out.println("设置GET请求参数出错:" + e.getMessage());
				e.printStackTrace();
			}
		}
		// 获取请求返回的结果.
		return readResponseContent(connection, Constants.CHARSET);
	}

	/**
	 * 设置Http请求的参数值.
	 * @param parameters 请求的参数值
	 * @param charset 参数值编码.
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	private static StringBuffer setHttpParams(Map<String, Object> parameters, String charset) {
		StringBuffer params = new StringBuffer();
		if (parameters != null && parameters.size() > 0) {
			for (Iterator<Entry<String, Object>> iter = parameters.entrySet().iterator(); iter.hasNext();) {
				Entry element = iter.next();
	            params.append(element.getKey().toString());
	            params.append("=");
	            try {
	            	// 对参数值使用URLEncoder.encode进行编码.
					params.append(URLEncoder.encode(element.getValue().toString(), charset));
				} catch (UnsupportedEncodingException e) {
					System.out.println("设置参数字符编码出错:" + e.getMessage());
					e.printStackTrace();
				}
	            params.append("&");
	        }
			// 删除最后一个&字符.
	        if (params.length() > 0) {
	            params = params.deleteCharAt(params.length() - 1);
	        }
		}
        return params;
	}

	/**
	 * 获取http请求返回的字符串信息.
	 * @param connection http连接.
	 * @param charset 输入流编码.
	 * @return
	 */
	private static String readResponseContent(HttpURLConnection connection, String charset) {
		StringBuffer buff = new StringBuffer(1024);
		InputStream is = null;
		BufferedReader in = null;
		try {
			String inputLine;
			// 进行连接
			try {
				connection.connect();
				// 取得输入流
				is = connection.getInputStream();
				in = new BufferedReader(new InputStreamReader(is, charset));
				while ((inputLine = in.readLine()) != null) {
					buff.append(inputLine + "\n");
				}
			} catch (IOException e) {
				System.out.println("获取输入流或者解析出错:" + e.getMessage());
				e.printStackTrace();
			}			
		} finally {
			try {
				in.close();
				is.close();
				// 断开连接
				connection.disconnect();
			} catch (Exception e) {
				System.out.println("关闭连接请求出錯：" + e.getMessage());
			}
		}
		return CommonUtil.trimString(buff.toString());
	}

	/**
	 * 设置SSLSocketFactory对象.
	 * @return
	 */
	private static SSLSocketFactory getSimpleSSLSocketFactory() {
		// 创建SSLContext对象,并使用我们指定的信任管理器初始化.
		TrustManager[] tm = { trustManager };
		SSLContext sslContext = null;
		try {
			sslContext = SSLContext.getInstance("SSL");
		} catch (NoSuchAlgorithmException e) {
			System.out.println("不存在SSL该算法：" + e.getMessage());
			e.printStackTrace();
		}
		try {
			sslContext.init(null, tm, new SecureRandom());
		} catch (KeyManagementException e) {
			// 处理密钥管理的操作的通用密钥管理异常.
			System.out.println("SSLContext对象初始化出错：" + e.getMessage());
			e.printStackTrace();
		}
		// 从上述SSLContext对象中得到SSLSocketFactory对象.
		return sslContext.getSocketFactory();
	}

	/**
	 * 实现自己的证书信任管理器类.
	 */
	private static X509TrustManager trustManager = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] xcs, String string)
                throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] xcs, String string)
                throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };

}
